﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MobileSales.Server.Database;
using MobileSales.Model.Exceptions;
using MobileSales.Common.Logger;

namespace MobileSales.Server.Services
{
    public class ParamService : ServiceBase, IParamService
    {
        #region GetParam
        public new MobileSales.Model.Params.Param GetParam(int paramId)
        {
            this.ValidateToken();
            return base.GetParam(paramId);
        }
        #endregion

        #region StoreParam

        public void StoreParam(MobileSales.Model.Params.Param param)
        {
            this.ValidateToken();
            string paramTypeString = param.ParamType.ToString();
            ParamType dbParamType = entities.ParamTypes.Where(x => x.Name.Equals(paramTypeString)).FirstOrDefault();
            if (dbParamType == null)
            {
                this.Raise(String.Format("Cannot find param type {0} in database!", param.ParamType.ToString()));
            }

            /* throws FormatException */
            if (param.DefaultValue != null)
            {
                try
                {
                    param.GetValue(param.DefaultValue);
                }
                catch (FormatException ex)
                {
                    CLogger.LogDebug(ex);
                    this.Raise(String.Format("Cannot parse initial value for {0}!", param.DisplayName));
                }
            }

            Param dbParam = null;
            if (param.Id != 0)
            {
                dbParam = entities.Params.Where(x => x.ParamId.Equals(param.Id)).FirstOrDefault();
                if (dbParam == null)
                {
                    this.Raise(String.Format("Update failed! Cannot find param which id is {0}", param.Id));
                }
            }
            if (dbParam == null)
            {
                dbParam = new Param();
            }

            dbParam.DefaultValue = (param.DefaultValue) ?? "";
            dbParam.Description = param.Description;
            dbParam.ParamType = dbParamType;
            dbParam.FieldType = MobileSales.Model.Params.FieldTypes.GetQualifiedName(param.FieldType);
            dbParam.ReadOnly = param.IsReadOnly;
            dbParam.Required = param.IsRequired;
            dbParam.MaxLength = param.MaxLength;
            dbParam.Name = param.Name;
            dbParam.DisplayName = param.DisplayName;

            if (param.Id == 0)
            {
                entities.Params.AddObject(dbParam);
            }
            entities.SaveChanges();
            this.NotifyAll(Util.ServiceType.ParamService, "GetParam", dbParam.ParamId);
        }

        #endregion

        #region RemoveParam
        public void RemoveParam(int paramId)
        {
            this.ValidateToken();
            var param = entities.Params.Where(x => x.ParamId.Equals(paramId)).FirstOrDefault();
            if (param != null)
            {
                entities.Params.DeleteObject(param);
                entities.SaveChanges();
                this.NotifyAll(Util.ServiceType.ParamService, "DeleteParam", paramId);
            }
            else
            {
                this.Raise("Delete failed! Could not find parameter!");
            }
        }
        #endregion

        #region GetParamList

        public IEnumerable<MobileSales.Model.Params.Param> GetParamList()
        {
            this.ValidateToken();
            return this.GetParamList(null);
        }

        public IEnumerable<MobileSales.Model.Params.Param> GetParamListByType(MobileSales.Model.Params.ParamType paramType)
        {
            this.ValidateToken();
            return this.GetParamList((MobileSales.Model.Params.ParamType?)paramType);
        }

        private IEnumerable<MobileSales.Model.Params.Param> GetParamList(MobileSales.Model.Params.ParamType? paramType)
        {
            string paramTypeString = (paramType.HasValue) ? paramType.Value.ToString() : null;
            IEnumerable<Param> dbParams = (paramType.HasValue)
                                            ? entities.Params.Where(x => x.ParamType.Name.Equals(paramTypeString))
                                            : entities.Params;
            if (dbParams != null)
            {
                List<MobileSales.Model.Params.Param> resultList = new List<MobileSales.Model.Params.Param>();
                foreach (var dbParam in dbParams)
                {
                    MobileSales.Model.Params.Param result = new MobileSales.Model.Params.Param()
                    {
                        Id = dbParam.ParamId,
                        DefaultValue = dbParam.DefaultValue,
                        Description = dbParam.Description,
                        ParamType = (MobileSales.Model.Params.ParamType)Enum.Parse(typeof(MobileSales.Model.Params.ParamType), dbParam.ParamType.Name),
                        FieldType = MobileSales.Model.Params.FieldTypes.GetFieldType(dbParam.FieldType),
                        IsReadOnly = dbParam.ReadOnly,
                        IsRequired = dbParam.Required,
                        MaxLength = dbParam.MaxLength,
                        DisplayName = dbParam.DisplayName,
                        Name = dbParam.Name
                    };
                    resultList.Add(result);
                }
                return resultList;
            }
            return null;
        }

        #endregion
    }
}
